//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Xml.Serialization;


namespace CommunityServer.Components
{
    /// <summary>
    /// The Permission enum identifies how the bits stored in the mask apply. If the bit is on in the allow mask
    /// then the right is allowed, if the bit is turned on in the deny mask then the right is turned off
    /// 
    /// Add more bit values to this enum as you extend the functionality of the software
    /// </summary>
    [Serializable]
    public abstract class PermissionBase 
    {
        #region Private Members
        int				settingsID;
        Guid			roleID;
        string roleName;
        int sectionID;
        ApplicationType appType = ApplicationType.Unknown;
        //Permission
        Permission		allowMask;
        Permission		denyMask;
        bool			implied;
        #endregion

        #region Cnstr
        public PermissionBase() 
        {
            settingsID = -1;
            allowMask = 0;
            denyMask = (Permission)(long)-1;
            implied	= true;
        }

        public PermissionBase( int site, Guid role, string name, Permission allow, Permission deny, bool impliedPermissions ) 
        {
            settingsID = site;
            roleID = role;
            roleName = name;
            allowMask = allow;
            denyMask = deny;
            implied = impliedPermissions;
        }
        #endregion

        #region Core Public Properties

        [XmlAttribute(AttributeName="settingsID")]
        public int SettingsID 
        {
            get{ return settingsID;}
            set{ settingsID = value; }
        }

        [XmlAttribute(AttributeName = "roleID", DataType="string")]
        public Guid RoleID 
        {
            get{ return roleID; }
            set{ roleID = value; }
        }

		/// <summary>
		/// Used when DataBinding for controls that dont support GUID (Like CA Grid)
		/// </summary>
		public string RoleIDString 
		{
			get{ return roleID.ToString(); }
		}

        [XmlAttribute(AttributeName = "name")]
        public string Name 
        {
            get{ return roleName; }
            set{ roleName = value; }
        }

        [XmlAttribute(AttributeName = "sectionID")]
        public int SectionID
        {
            get {return sectionID;}
            set {sectionID = value;}
        }

        [XmlAttribute(AttributeName = "implied")]
        public bool Implied 
        {
            get{ return implied; }
            set{ implied = value; }
        }

        [XmlAttribute(AttributeName = "allowMask", DataType="long")]
        public Permission AllowMask 
        {
            get{ return allowMask; }
            set{ allowMask = value; }
        }

        [XmlAttribute(AttributeName = "denyMask", DataType = "long")]
        public Permission DenyMask 
        {
            get{ return denyMask; }
            set{ denyMask = value; }
        }

        [XmlAttribute(AttributeName="applicationType", DataType = "string")]
        public ApplicationType ApplicationType 
        {
            get{ return appType; }
            set{ appType = value; }
        }
        #endregion

        #region GetBin
        public bool GetBit( Permission mask ) 
        {
            bool bReturn = false;
				
            if(( denyMask & mask ) == mask )
                bReturn = false;

            if(( allowMask & mask ) == mask )
                bReturn = true;
				
            return bReturn;
        }
        #endregion

        #region Public Methods

        public void SetBit( Permission mask, AccessControlEntry accessControl ) 
        {

            switch( accessControl )
            {
                case AccessControlEntry.Allow:
                    allowMask	|= (Permission)((long)mask & (long)-1);
                    denyMask	&= ~(Permission)((long)mask & (long)-1);
                    break;
                case AccessControlEntry.NotSet:
                    allowMask	&= ~(Permission)((long)mask & (long)-1);
                    denyMask	&= ~(Permission)((long)mask & (long)-1);
                    break;
                default:
                    allowMask	&= ~(Permission)((long)mask & (long)-1);
                    denyMask	|= (Permission)((long)mask & (long)-1);
                    break;
            }
        }
		/// <summary>
		/// This method merges the supplied permissions with the current permissions to come up with an
		/// updated permission set. The logic is that and Implied Allow overrides an Implied Deny, but 
		/// and Explicit Deny overrides an Implicit Allow, while an Explicit Allow overrides an Explicit
		/// Deny. This gives us a least restrictive security system.
		/// </summary>
		/// <param name="permissionBase">The permission to merge with the current permission set</param>
        public void Merge( PermissionBase permissionBase ) 
        {
            this.allowMask	|= permissionBase.AllowMask;
            this.denyMask	|= permissionBase.DenyMask;
        }

        #endregion

        public static void RedirectOrExcpetion(CSExceptionType csEx)
        {
            CSContext context = CSContext.Current;

            if(context.IsWebRequest && !context.IsAuthenticated)
            {
                context.Context.Response.Redirect(Globals.GetSiteUrls().Login);
                context.Context.Response.End();
            }
            else
                throw new CSException(csEx);
        }

        public static void RedirectOrExcpetion(CSExceptionType csEx, string message)
        {
            CSContext context = CSContext.Current;

            if(context.IsWebRequest && !context.IsAuthenticated)
            {
                context.Context.Response.Redirect(Globals.GetSiteUrls().Login);
                context.Context.Response.End();
            }
            else
                throw new CSException(csEx, message);
        }

    }

 
 

    /// <summary>
    /// Signature for a method which can check a user's permissions to a section
    /// </summary>
    public delegate void AccessCheckDelegate(Section section, Permission permission, User user, Post post);

    /// <summary>
    /// Signature for a mthod which can validate a user's permissions. returns true if the user can access the section
    /// </summary>
    public delegate bool ValidatePermissionsDelegate(Section section, Permission permission, User user, Post p);

}
